import wx
from AddBLFrame import AddBLFrame
from vtk.wx.wxVTKRenderWindowInteractor import wxVTKRenderWindowInteractor
from vtk import vtkInteractorStyleTrackballCamera, vtkRenderer, vtkCellPicker

##  AddBonyLandmark contains the functionality behind the AddBLFrame.
class AddBonyLandmark:

    ##  The constructor of AddBonyLandmark. Here, the 3D model and Cellpicker are loaded.
    #   @param[in]  parent  The wx window parent (notebook) of this panel.
    #   @param[in]  gui     GUI instance.
    def __init__(self,parent,gui):
        ##  GUI instance.
        self.gui = gui
        ##  Instance of the AddBlFrame class.
        self._addblframe = AddBLFrame(gui,parent)
        self._addblframe.Show()
        self._addblframe.rwi.SetInteractorStyle(vtkInteractorStyleTrackballCamera())

        ##  Flag that indicates whether the program is recording.
        self.RECORDING = False
        # Initialize VTK.
        self.gui.main.states.visualization.InitiateVTK(self)
        # Initialize 3D model, disables the sensor and bony landmark spheres by passing 0 values.
        self.gui.main.states.visualization.SetRenderActors(self,0,0,0)
        # Set the 3D model parts to visible.
        for j in range(0, len(self.actorList)): self.actorList[j].VisibilityOn()
        # Position the 3D model correctly.
        self.ren.ResetCamera()
        self.ren.GetActiveCamera().Azimuth(90)
        self.ren.GetActiveCamera().Roll(180)

        self._addblframe.rwi.GetRenderWindow().AddRenderer(self.ren)
        self._addblframe.rwi.GetRenderWindow().SetAAFrames(3)
        ##  The vtkCellPicker used to get 3D coordinates.
        self.cellpicker = vtkCellPicker()
        self.cellpicker.SetTolerance(0.005)
        self.cellpicker.InitializePickList()
        # Add props to the PickList.
        for j in range(0, len(self.actorList)):
            self.cellpicker.AddPickList(self.actorList[j])
        self.cellpicker.PickFromListOn()
        ##  The event listening for right mouseclicks.
        self.rbpe = self._addblframe.rwi.AddObserver("RightButtonPressEvent", self.PointPicked, 1.0)

        self.__BindEvents()

    ##  Binds items of the panel to event handlers.
    def __BindEvents(self):
        self._addblframe.Bind(wx.EVT_BUTTON, self.OnHelp, self._addblframe.help_button)
        self._addblframe.Bind(wx.EVT_BUTTON, self.OnFinish, self._addblframe.finish_button)
        self._addblframe.Bind(wx.EVT_CLOSE, self.OnClose)

    ##  Picks a point on the 3D model and adds it to the list when the right mouse button is pressed.
    #   @param[in]  object_binding  Automatically passed parameter.
    #   @param[in]  event_name      Automatically passed parameter.
    def PointPicked(self, object_binding, event_name):
        x,y = object_binding.GetEventPosition()
        self.cellpicker.Pick(x,y,0.0,self.ren)
        ##  The point clicked on by the mouse.
        self.pickPos = self.cellpicker.GetPickPosition()
        result = "".join(['%.1f ' % round(self.pickPos[i], 1) for i in range (0,3)])
        self._addblframe.bony_landmarks_listctrl.InsertStringItem(0, result)

    ## Displays a help dialog for the user.
    def OnHelp(self,event):
        msg = "To pick a coordinate, right click on the model at the desired position. The coordinate will then be added to the list.\nYou can rotate the model by clicking and holding the left mouse button. Zooming in and out of the model is possible using the scroll wheel.\nWhen all the desired positions have been picked, click on the Finish button."
        dlg = wx.MessageDialog(self._addblframe, msg, 'Picking a position', wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()

    ##  Copies the 3D coordinates to the clipboard and closes the AddBonyLandmark frame.
    def OnFinish(self,event):
        result = "".join([self._addblframe.bony_landmarks_listctrl.GetItemText(i)+"\r\n" for i in range(self._addblframe.bony_landmarks_listctrl.GetItemCount())])
        string = wx.TextDataObject(result)
        wx.TheClipboard.Open()
        wx.TheClipboard.SetData(string)
        wx.TheClipboard.Close()

        msg = "The new coordinates have been copied to the clipboard.\nYou may now add the name, description, rule and picture using the configuration file."
        dlg = wx.MessageDialog(self._addblframe, msg, 'Measurement completed', wx.OK | wx.ICON_INFORMATION)
        dlg.ShowModal()
        self._addblframe.rwi.RemoveObserver(self.rbpe)
        self._addblframe.Close()

    ##  Overwrites the standard OnClose method, this is needed to prevent the vtkRenderer from getting destroyed.
    def OnClose(self,event):
        try:
            if self.gui.notebook.GetCurrentPage().name == "Visualization":
                if self.gui.notebook.GetCurrentPage().visNotebook.GetCurrentPage().name == "Playback":
                    self._addblframe.rwi.Destroy()
                    self.gui.main.states.visualization.InitiateVTK(self)
                    event.Skip()
                else:
                    self.gui.main.states.visualization.InitiateVTK(self)
                    event.Skip()
            else:
                event.Skip()
        # Sometimes a wglMakeCurrent error occurs, preventing the frame from being closed.
        except:
            self._addblframe.Destroy()